package cn.donting.jme.edit.project;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

@Getter
@Slf4j
/**
 * 项目
 */
public class Project {

    /**
     * 项目的类加载器
     */
    private ProjectClassLoader projectClassLoader;

    /**
     * 项目的 依赖类表文件
     * 由gradle task 创建
     * @see Project#creatClassPathFile
     */
    public static final String CLASSPATH_FILE_NAME = "runtimeClasspath.classpath";
    /**
     * 项目文件夹路径
     * project-template/
     */
    private File file;

    /**
     * 源码路径
     */
    private File scr;
    /**
     * resources 路径
     */
    private File resources;


    private Project(File file) {
        this.file = file;
        String prePath = file.toString() + File.separator + "src" + File.separator;
        scr = new File(prePath + "main" + File.separator + "java");
        resources = new File(prePath + "main" + File.separator + "resources");

    }

    /**
     * 重新加载
     * 编译
     * URLClassLoader
     * 检查  SceneEditState
     * TODO:// Project 重新加载
     */
    public void reload() {
    }


    /**
     * 类加载加载器
     */
    private void loadProjectClassLoader() {
        try {
            ArrayList<URL> urls = new ArrayList<>();
            File file = new File(this.file.toString() + File.separator + CLASSPATH_FILE_NAME);
            BufferedReader out = new BufferedReader(new FileReader(file));
            List<String> collect = out.lines().collect(Collectors.toList());
            for (String path : collect) {
                if (path.length() > 0) {
                    URL url = new File(path).toURL();
                    urls.add(url);
                }
            }
            projectClassLoader = new ProjectClassLoader(urls.toArray(new URL[urls.size()]), this, Project.class.getClassLoader());
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            throw new RuntimeException(ex.getMessage(), ex);
        }
    }

    /**
     * 生成项目的classPath
     * 本质执行 gradlew 命令
     */
    private void creatClassPathFile() {
        try {
            Properties properties = System.getProperties();
            String osName = properties.getProperty("os.name");
            String cmd = "gradlew";
            if (osName.toLowerCase().contains("windows")) {
                cmd = "gradlew.bat";
            }
            Runtime runtime = Runtime.getRuntime();
            Process ls = runtime.exec(file.toString() + File.separator + cmd);
            InputStream outputStream = ls.getInputStream();
            byte[] bytes = new byte[2048];
            int len;
            while ((len = outputStream.read(bytes)) != -1) {
                System.out.print(new String(bytes, 0, len, "gbk"));
            }
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取上一次打开的 j3e 文件
     * @return
     */
    public File getLastOpenJ3eFile(){
        return null;
    }

    /**
     * 打开项目
     *
     * @param file 项目目录
     * @return
     * @throws IOException
     */
    public static Project openProject(File file) throws IOException {
        if (!file.isDirectory()) {
            throw new IOException(file.toString() + " 不是一个文件夹");
        }
        return new Project(file);
    }



    /**
     * 替换文本中的字符
     *
     * @param file   文件
     * @param oldStr 需要替换的字符
     * @param newStr 新字符
     * @throws IOException
     */
    private static void fileStrReplace(File file, String oldStr, String newStr) throws IOException {
        FileInputStream settingsInputStream = new FileInputStream(file);
        int available = settingsInputStream.available();
        byte[] bytes1 = new byte[available];
        settingsInputStream.read(bytes1);
        settingsInputStream.close();
        String s = new String(bytes1);
        s = s.replace(oldStr, newStr);
        FileOutputStream fileOutputStream1 = new FileOutputStream(file);
        fileOutputStream1.write(s.getBytes());
        fileOutputStream1.close();
    }

    /**
     * 创建项目
     *
     * @param path        项目存放目录
     * @param group       组
     * @param projectName 项目名/artifactId
     * @throws IOException
     */
    private static void creatProject(String path, String group, String projectName) throws IOException {
        ClassLoader classLoader = Project.class.getClassLoader();
        URL resource = classLoader.getResource("projectTemplate.zip");

        File file = new File(System.getProperty("user.dir") + File.separator + "projectTemplate.zip");
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        InputStream inputStream = resource.openStream();

        byte[] bytes = new byte[1024];
        int len;
        while ((len = inputStream.read(bytes)) != -1) {
            fileOutputStream.write(bytes, 0, len);
        }
        inputStream.close();
        fileOutputStream.close();
        ZipFile zipFile = new ZipFile(file);
        new File(path).mkdirs();

        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry zipEntry = entries.nextElement();
            File outFile = new File(path + File.separator + zipEntry.getName());
            if (zipEntry.isDirectory()) {
                outFile.mkdirs();
            } else {
                InputStream zipEntryInputStream = zipFile.getInputStream(zipEntry);
                FileOutputStream fileOutputStream1 = new FileOutputStream(outFile);
                while ((len = zipEntryInputStream.read(bytes)) != -1) {
                    fileOutputStream1.write(bytes, 0, len);
                }
                zipEntryInputStream.close();
                fileOutputStream1.close();
            }

        }
        //替换 projectName group
        String settingsGradle = path + File.separator + "settings.gradle";
        File file1 = new File(settingsGradle);
        fileStrReplace(file1, "project-template", projectName);

        String buildGradle = path + File.separator + "build.gradle";
        file1 = new File(buildGradle);
        fileStrReplace(file1, "org.example", group);
    }

    public static void main(String[] args) throws IOException {
        creatProject("E:\\project\\My-projectd\\project", "cn.donting", "testPricj");
    }

}
